/* eslint-disable max-statements */ import type { ParsedUrlQuery } from 'querystring'; import type { GetStaticPaths, GetStaticProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { type FC, useCallback } from 'react'; import { useIntl } from 'react-intl'; import { getLayout, Heading, LinksWidget, PostsList, Pagination, type RenderPaginationLink, type RenderPaginationItemAriaLabel, Page, PageHeader, PageBody, PageSidebar, Spinner, Notice, LoadingPage, } from '../../../components'; import { convertWPThematicPreviewToPageLink, convertWPTopicPreviewToPageLink, fetchLastPostCursor, fetchPostsCount, fetchPostsList, fetchThematicsCount, fetchThematicsList, fetchTopicsCount, fetchTopicsList, } from '../../../services/graphql'; import styles from '../../../styles/pages/blog.module.scss'; import type { GraphQLConnection, Maybe, NextPageWithLayout, Nullable, WPPostPreview, WPThematicPreview, WPTopicPreview, } from '../../../types'; import { CONFIG } from '../../../utils/config'; import { ARTICLE_ID, PAGINATED_ROUTE_PREFIX, ROUTES, } from '../../../utils/constants'; import { getBlogGraph, getLinksItemData, getPostsWithUrl, getSchemaFrom, getWebPageGraph, } from '../../../utils/helpers'; import { loadTranslation, type Messages } from '../../../utils/helpers/server'; import { useArticlesList, useBreadcrumbs, useRedirection, useThematicsList, useTopicsList, } from '../../../utils/hooks'; const renderPaginationLink: RenderPaginationLink = (pageNum) => { if (pageNum === 1) return ROUTES.BLOG; return `${ROUTES.BLOG}${PAGINATED_ROUTE_PREFIX}/${pageNum}`; }; type BlogPageProps = { data: { posts: GraphQLConnection; thematics: GraphQLConnection; topics: GraphQLConnection; totalPosts: number; }; lastCursor: Maybe>; pageNumber: number; translation: Messages; }; const Blog: FC> = ({ data, lastCursor, pageNumber, }) => { const intl = useIntl(); const { articles, error, firstNewResultIndex, isLoading, isLoadingMore, isRefreshing, hasNextPage, loadMore, } = useArticlesList({ after: lastCursor, fallback: [data.posts], perPage: CONFIG.postsPerPage, }); const { isLoading: areThematicsLoading, thematics } = useThematicsList({ fallback: data.thematics, input: { first: data.thematics.pageInfo.total }, }); const { isLoading: areTopicsLoading, topics } = useTopicsList({ fallback: data.topics, input: { first: data.topics.pageInfo.total }, }); const messages = { loading: { thematicsList: intl.formatMessage({ defaultMessage: 'Thematics are loading...', description: 'BlogPage: loading thematics message', id: 'y37FuH', }), topicsList: intl.formatMessage({ defaultMessage: 'Topics are loading...', description: 'BlogPage: loading topics message', id: 'OsclKU', }), }, pageTitle: intl.formatMessage( { defaultMessage: 'Blog - Page {number}', description: 'BlogPage: page title with number', id: '8xVO3Y', }, { number: pageNumber, } ), pagination: { title: intl.formatMessage({ defaultMessage: 'Pagination', description: 'BlogPage: pagination accessible name', id: 'AXe1Iz', }), }, seo: { metaDesc: intl.formatMessage( { defaultMessage: "Discover {websiteName}'s writings. He talks about web development, Linux and open source mostly.", description: 'BlogPage: SEO - Meta description', id: '18h/t0', }, { websiteName: CONFIG.name } ), title: intl.formatMessage( { defaultMessage: 'Blog: development, open source - Page {number} - {websiteName}', description: 'BlogPage: SEO - Page title', id: 'dG3sT3', }, { number: pageNumber, websiteName: CONFIG.name } ), }, widgets: { thematicsListTitle: intl.formatMessage({ defaultMessage: 'Thematics', description: 'BlogPage: thematics list widget title', id: 'HriY57', }), topicsListTitle: intl.formatMessage({ defaultMessage: 'Topics', description: 'BlogPage: topics list widget title', id: '2D9tB5', }), }, }; const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumbs( messages.pageTitle ); const jsonLd = getSchemaFrom([ getWebPageGraph({ breadcrumb: breadcrumbSchema, description: messages.seo.metaDesc, slug: ROUTES.BLOG, title: messages.pageTitle, }), getBlogGraph({ description: '', posts: articles?.flatMap((page) => page.edges.map(({ node }) => { return { '@id': `${node.slug}#${ARTICLE_ID}` }; }) ), slug: ROUTES.BLOG, title: messages.pageTitle, }), ]); const renderPaginationLabel: RenderPaginationItemAriaLabel = useCallback( ({ kind, pageNumber: number, isCurrentPage }) => { switch (kind) { case 'backward': return intl.formatMessage( { defaultMessage: 'Go to previous page, page {number}', description: 'BlogPage: previous page label', id: 'faO6BQ', }, { number } ); case 'forward': return intl.formatMessage( { defaultMessage: 'Go to next page, page {number}', description: 'BlogPage: next page label', id: 'oq3BzP', }, { number } ); case 'number': default: return isCurrentPage ? intl.formatMessage( { defaultMessage: 'Current page, page {number}', description: 'BlogPage: current page label', id: 'JL6G22', }, { number } ) : intl.formatMessage( { defaultMessage: 'Go to page {number}', description: 'BlogPage: page number label', id: 'IVczxR', }, { number } ); } }, [intl] ); const pageUrl = `${CONFIG.url}${ROUTES.BLOG}`; return ( {messages.seo.title} {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */} {/*eslint-disable-next-line react/jsx-no-literals -- Content allowed */}